import datetime
from bson import ObjectId
from pymongo import MongoClient, ASCENDING
import bcrypt

def hash_password(password):
    """对密码进行哈希处理"""
    return bcrypt.hashpw(password.encode('utf-8'), bcrypt.gensalt()).decode('utf-8')

def init_database(mongo_uri='mongodb://localhost:27017/medical_system'):
    """初始化数据库基础数据"""
    # 连接数据库
    client = MongoClient(mongo_uri)
    db = client.medical_system
    
    # 创建索引
    create_indexes(db)
    
    # 初始化角色
    init_roles(db)
    
    # 初始化部门
    init_departments(db)
    
    # 初始化默认用户
    init_users(db)
    
    # 初始化药品分类
    init_drug_categories(db)
    
    # 关闭连接
    client.close()
    
    print("数据库初始化完成")

def create_indexes(db):
    """创建索引"""
    try:
        from pymongo import ASCENDING, DESCENDING
        
        # 用户集合索引
        if 'username_1' not in db.users.index_information():
            db.users.create_index([('username', ASCENDING)], unique=True)
        if 'email_1' not in db.users.index_information():
            db.users.create_index([('email', ASCENDING)], unique=True)
        if 'staffId_1' not in db.users.index_information():
            db.users.create_index([('staffId', ASCENDING)], unique=True)
        
        # 角色集合索引
        if 'name_1' not in db.roles.index_information():
            db.roles.create_index([('name', ASCENDING)], unique=True)
        
        # 部门集合索引
        if 'name_1' not in db.departments.index_information():
            db.departments.create_index([('name', ASCENDING)], unique=True)
        if 'code_1' not in db.departments.index_information():
            db.departments.create_index([('code', ASCENDING)], unique=True)
        
        # 医生集合索引
        if 'staffId_1' not in db.doctors.index_information():
            db.doctors.create_index([('staffId', ASCENDING)], unique=True)
        if 'departmentId_1' not in db.doctors.index_information():
            db.doctors.create_index([('departmentId', ASCENDING)])
        if 'name_1' not in db.doctors.index_information():
            db.doctors.create_index([('name', ASCENDING)])
        
        # 患者集合索引
        if 'patientId_1' not in db.patients.index_information():
            db.patients.create_index([('patientId', ASCENDING)], unique=True)
        if 'idNumber_1' not in db.patients.index_information():
            db.patients.create_index([('idNumber', ASCENDING)])
        if 'name_1' not in db.patients.index_information():
            db.patients.create_index([('name', ASCENDING)])
        
        # 药品集合索引
        if 'drugCode_1' not in db.drugs.index_information():
            db.drugs.create_index([('drugCode', ASCENDING)], unique=True)
        if 'name_1' not in db.drugs.index_information():
            db.drugs.create_index([('name', ASCENDING)])
        
        # 医嘱集合索引
        if 'orderId_1' not in db.medical_orders.index_information():
            db.medical_orders.create_index([('orderId', ASCENDING)], unique=True)
        
        # 文件集合索引
        if 'relatedId_1' not in db.files.index_information():
            db.files.create_index([('relatedId', ASCENDING)])
        if 'relatedType_1' not in db.files.index_information():
            db.files.create_index([('relatedType', ASCENDING)])
        if 'type_1' not in db.files.index_information():
            db.files.create_index([('type', ASCENDING)])
        if 'uploadBy_1' not in db.files.index_information():
            db.files.create_index([('uploadBy', ASCENDING)])
        if 'createdAt_1' not in db.files.index_information():
            db.files.create_index([('createdAt', ASCENDING)])
        
        print("数据库索引创建完成")
    except Exception as e:
        print(f"创建索引失败: {str(e)}")

def init_roles(db):
    """初始化角色数据"""
    now = datetime.datetime.utcnow()
    
    # 系统管理员角色
    admin_role = {
        'name': 'admin',
        'displayName': '系统管理员',
        'description': '系统超级管理员，拥有所有权限',
        'permissions': [
            # 用户管理权限
            'user:read', 'user:create', 'user:update', 'user:delete',
            # 角色管理权限
            'role:read', 'role:create', 'role:update', 'role:delete',
            # 部门管理权限
            'department:read', 'department:create', 'department:update', 'department:delete',
            # 患者管理权限
            'patient:read', 'patient:create', 'patient:update', 'patient:delete',
            # 医生管理权限
            'doctor:read', 'doctor:create', 'doctor:update', 'doctor:delete',
            # 药品管理权限
            'drug:read', 'drug:create', 'drug:update', 'drug:delete',
            # 医疗记录权限
            'medical_record:read', 'medical_record:create', 'medical_record:update', 'medical_record:delete',
            # 处方管理权限
            'prescription:read', 'prescription:create', 'prescription:update', 'prescription:audit', 'prescription:dispense',
            # 预约管理权限
            'appointment:read', 'appointment:create', 'appointment:update', 'appointment:delete', 'appointment:checkin', 'appointment:payment',
            # 排班管理权限
            'schedule:read', 'schedule:create', 'schedule:update', 'schedule:delete',
            # 库存管理权限
            'drug_inventory:read', 'drug_inventory:create', 'drug_inventory:update',
            # 医嘱管理权限
            'medical_order:read', 'medical_order:create', 'medical_order:update', 'medical_order:delete', 'medical_order:execute',
            # 报表权限
            'report:read', 'report:generate',
            # 财务权限
            'payment:read', 'payment:create', 'payment:update',
            'invoice:read', 'invoice:create', 'invoice:update',
            # 文件权限
            'file:upload', 'file:read', 'file:delete'
        ],
        'status': '启用',
        'createdAt': now,
        'updatedAt': now
    }
    
    # 医生角色
    doctor_role = {
        'name': 'doctor',
        'displayName': '医生',
        'description': '医生角色，负责诊断、开方和治疗',
        'permissions': [
            'patient:read',
            'medical_record:read', 'medical_record:create', 'medical_record:update',
            'prescription:read', 'prescription:create', 'prescription:audit',
            'appointment:read',
            'drug:read'
        ],
        'status': '启用',
        'createdAt': now,
        'updatedAt': now
    }
    
    # 护士角色
    nurse_role = {
        'name': 'nurse',
        'displayName': '护士',
        'description': '护士角色，负责辅助医生和照护患者',
        'permissions': [
            'patient:read',
            'medical_record:read',
            'appointment:read',
            'prescription:read'
        ],
        'status': '启用',
        'createdAt': now,
        'updatedAt': now
    }
    
    # 药剂师角色
    pharmacist_role = {
        'name': 'pharmacist',
        'displayName': '药剂师',
        'description': '药剂师角色，负责药品管理和处方审核',
        'permissions': [
            'drug:read',
            'drug_inventory:read', 'drug_inventory:update',
            'prescription:read', 'prescription:audit', 'prescription:dispense'
        ],
        'status': '启用',
        'createdAt': now,
        'updatedAt': now
    }
    
    # 前台角色
    receptionist_role = {
        'name': 'receptionist',
        'displayName': '前台',
        'description': '前台角色，负责患者接待、挂号和收款',
        'permissions': [
            'patient:read', 'patient:create', 'patient:update',
            'appointment:read', 'appointment:create', 'appointment:update', 'appointment:checkin', 'appointment:payment',
            'payment:read', 'payment:create',
            'invoice:read', 'invoice:create'
        ],
        'status': '启用',
        'createdAt': now,
        'updatedAt': now
    }
    
    # 患者角色
    patient_role = {
        'name': 'patient',
        'displayName': '患者',
        'description': '患者角色，可以查看自己的医疗记录和预约',
        'permissions': [
            'medical_record:read',
            'prescription:read',
            'appointment:read', 'appointment:create'
        ],
        'status': '启用',
        'createdAt': now,
        'updatedAt': now
    }
    
    # 定义所有角色
    roles = [
        admin_role, doctor_role, nurse_role, 
        pharmacist_role, receptionist_role, patient_role
    ]
    
    # 逐个检查角色并插入或更新
    roles_count = 0
    for role in roles:
        existing_role = db.roles.find_one({'name': role['name']})
        if not existing_role:
            db.roles.insert_one(role)
            roles_count += 1
            print(f"创建角色: {role['name']} ({role['displayName']})")
        else:
            # 可选：更新已存在角色的权限
            db.roles.update_one(
                {'name': role['name']}, 
                {'$set': {
                    'permissions': role['permissions'],
                    'updatedAt': now
                }}
            )
            print(f"更新角色权限: {role['name']} ({role['displayName']})")
    
    print(f"角色初始化完成，新增 {roles_count} 个角色")

def init_departments(db):
    """初始化部门数据"""
    # 检查departments集合是否为空
    if db.departments.count_documents({}) == 0:
        now = datetime.datetime.utcnow()
        
        # 临床科室
        clinical_departments = [
            {
                'name': '内科',
                'code': 'NK',
                'description': '负责内科疾病的诊断和治疗',
                'category': '临床',
                'order': 10,
                'status': '启用',
                'createdAt': now,
                'updatedAt': now
            },
            {
                'name': '外科',
                'code': 'WK',
                'description': '负责外科手术和治疗',
                'category': '临床',
                'order': 20,
                'status': '启用',
                'createdAt': now,
                'updatedAt': now
            },
            {
                'name': '儿科',
                'code': 'EK',
                'description': '专注于儿童疾病的诊断和治疗',
                'category': '临床',
                'order': 30,
                'status': '启用',
                'createdAt': now,
                'updatedAt': now
            },
            {
                'name': '妇产科',
                'code': 'FCK',
                'description': '专注于妇科疾病和产科服务',
                'category': '临床',
                'order': 40,
                'status': '启用',
                'createdAt': now,
                'updatedAt': now
            },
            {
                'name': '神经内科',
                'code': 'SJNK',
                'description': '负责神经系统疾病的诊断和治疗',
                'category': '临床',
                'order': 50,
                'status': '启用',
                'createdAt': now,
                'updatedAt': now
            },
            {
                'name': '心内科',
                'code': 'XNK',
                'description': '负责心脏疾病的诊断和治疗',
                'category': '临床',
                'order': 60,
                'status': '启用',
                'createdAt': now,
                'updatedAt': now
            },
            {
                'name': '骨科',
                'code': 'GK',
                'description': '负责骨骼和关节疾病的诊断和治疗',
                'category': '临床',
                'order': 70,
                'status': '启用',
                'createdAt': now,
                'updatedAt': now
            },
            {
                'name': '皮肤科',
                'code': 'PFK',
                'description': '负责皮肤疾病的诊断和治疗',
                'category': '临床',
                'order': 80,
                'status': '启用',
                'createdAt': now,
                'updatedAt': now
            }
        ]
        
        # 医技科室
        medical_tech_departments = [
            {
                'name': '放射科',
                'code': 'FSK',
                'description': '负责X光、CT、核磁共振等影像检查',
                'category': '医技',
                'order': 110,
                'status': '启用',
                'createdAt': now,
                'updatedAt': now
            },
            {
                'name': '检验科',
                'code': 'JYK',
                'description': '负责临床检验和化验',
                'category': '医技',
                'order': 120,
                'status': '启用',
                'createdAt': now,
                'updatedAt': now
            },
            {
                'name': '药剂科',
                'code': 'YJK',
                'description': '负责药品管理和处方审核',
                'category': '医技',
                'order': 130,
                'status': '启用',
                'createdAt': now,
                'updatedAt': now
            },
            {
                'name': '病理科',
                'code': 'BLK',
                'description': '负责病理学检查和诊断',
                'category': '医技',
                'order': 140,
                'status': '启用',
                'createdAt': now,
                'updatedAt': now
            }
        ]
        
        # 行政科室
        admin_departments = [
            {
                'name': '人事科',
                'code': 'RSK',
                'description': '负责人事管理和招聘',
                'category': '行政',
                'order': 210,
                'status': '启用',
                'createdAt': now,
                'updatedAt': now
            },
            {
                'name': '财务科',
                'code': 'CWK',
                'description': '负责财务管理和会计',
                'category': '行政',
                'order': 220,
                'status': '启用',
                'createdAt': now,
                'updatedAt': now
            },
            {
                'name': '信息科',
                'code': 'XXK',
                'description': '负责信息系统维护和管理',
                'category': '行政',
                'order': 230,
                'status': '启用',
                'createdAt': now,
                'updatedAt': now
            }
        ]
        
        # 其他科室
        other_departments = [
            {
                'name': '急诊科',
                'code': 'JZK',
                'description': '负责紧急医疗服务',
                'category': '其他',
                'order': 310,
                'status': '启用',
                'createdAt': now,
                'updatedAt': now
            },
            {
                'name': '康复科',
                'code': 'KFK',
                'description': '负责患者康复治疗',
                'category': '其他',
                'order': 320,
                'status': '启用',
                'createdAt': now,
                'updatedAt': now
            }
        ]
        
        # 合并所有部门
        all_departments = clinical_departments + medical_tech_departments + admin_departments + other_departments
        
        # 插入部门数据
        db.departments.insert_many(all_departments)
        
        print("部门初始化完成")
    else:
        print("部门数据已存在，跳过初始化")

def init_users(db):
    """初始化默认用户"""
    # 检查users集合是否有管理员用户
    if db.users.count_documents({'username': 'admin'}) == 0:
        now = datetime.datetime.utcnow()
        
        # 创建系统管理员
        admin_user = {
            'username': 'admin',
            'password': hash_password('admin123'),
            'name': '系统管理员',
            'email': 'admin@example.com',
            'phone': '13800000000',
            'role': 'admin',
            'status': 'active',
            'createdAt': now,
            'updatedAt': now
        }
        
        # 创建默认医生用户
        doctor_user = {
            'username': 'doctor',
            'password': hash_password('doctor123'),
            'name': '张医生',
            'email': 'doctor@example.com',
            'phone': '13800000001',
            'role': 'doctor',
            'departmentId': str(db.departments.find_one({'code': 'NK'})['_id']) if db.departments.find_one({'code': 'NK'}) else None,
            'status': 'active',
            'createdAt': now,
            'updatedAt': now
        }
        
        # 创建默认护士用户
        nurse_user = {
            'username': 'nurse',
            'password': hash_password('nurse123'),
            'name': '李护士',
            'email': 'nurse@example.com',
            'phone': '13800000002',
            'role': 'nurse',
            'departmentId': str(db.departments.find_one({'code': 'NK'})['_id']) if db.departments.find_one({'code': 'NK'}) else None,
            'status': 'active',
            'createdAt': now,
            'updatedAt': now
        }
        
        # 创建默认药剂师用户
        pharmacist_user = {
            'username': 'pharmacist',
            'password': hash_password('pharmacist123'),
            'name': '王药师',
            'email': 'pharmacist@example.com',
            'phone': '13800000003',
            'role': 'pharmacist',
            'departmentId': str(db.departments.find_one({'code': 'YJK'})['_id']) if db.departments.find_one({'code': 'YJK'}) else None,
            'status': 'active',
            'createdAt': now,
            'updatedAt': now
        }
        
        # 创建默认前台用户
        receptionist_user = {
            'username': 'receptionist',
            'password': hash_password('receptionist123'),
            'name': '赵前台',
            'email': 'receptionist@example.com',
            'phone': '13800000004',
            'role': 'receptionist',
            'status': 'active',
            'createdAt': now,
            'updatedAt': now
        }
        
        # 插入用户数据
        db.users.insert_many([
            admin_user, doctor_user, nurse_user, 
            pharmacist_user, receptionist_user
        ])
        
        print("默认用户初始化完成")
    else:
        print("管理员用户已存在，跳过用户初始化")

def init_drug_categories(db):
    """初始化药品分类"""
    # 检查drug_categories集合是否为空
    if not db.drug_categories.find_one():
        now = datetime.datetime.utcnow()
        
        categories = [
            {
                'name': '西药',
                'code': 'XY',
                'description': '西药类别',
                'order': 1,
                'status': '启用',
                'createdAt': now,
                'updatedAt': now
            },
            {
                'name': '中成药',
                'code': 'ZCY',
                'description': '中成药类别',
                'order': 2,
                'status': '启用',
                'createdAt': now,
                'updatedAt': now
            },
            {
                'name': '中药饮片',
                'code': 'ZYYP',
                'description': '中药饮片类别',
                'order': 3,
                'status': '启用',
                'createdAt': now,
                'updatedAt': now
            },
            {
                'name': '生物制品',
                'code': 'SWZP',
                'description': '生物制品类别',
                'order': 4,
                'status': '启用',
                'createdAt': now,
                'updatedAt': now
            }
        ]
        
        db.drug_categories.insert_many(categories)
        print("药品分类初始化完成")
    else:
        print("药品分类已存在，跳过初始化")

def init_db():
    """初始化数据库"""
    try:
        from app import mongo
        db = mongo.db
        
        # 创建角色集合
        if 'roles' not in db.list_collection_names():
            db.create_collection('roles')
            print("已创建roles集合")
        
        # 创建部门集合
        if 'departments' not in db.list_collection_names():
            db.create_collection('departments')
            print("已创建departments集合")
        
        # 创建医生集合
        if 'doctors' not in db.list_collection_names():
            db.create_collection('doctors')
            db.doctors.create_index('staffId', unique=True)
            print("已创建doctors集合")
        
        # 创建患者集合
        if 'patients' not in db.list_collection_names():
            db.create_collection('patients')
            db.patients.create_index('patientId', unique=True)
            print("已创建patients集合")
        
        # 创建病历集合
        if 'medical_records' not in db.list_collection_names():
            db.create_collection('medical_records')
            print("已创建medical_records集合")
        
        # 创建医嘱集合
        if 'medical_orders' not in db.list_collection_names():
            db.create_collection('medical_orders')
            db.medical_orders.create_index('orderId', unique=True)
            print("已创建medical_orders集合")
        
        # 创建药品集合
        if 'drugs' not in db.list_collection_names():
            db.create_collection('drugs')
            db.drugs.create_index('drugCode', unique=True)
            print("已创建drugs集合")
        
        # 创建文件集合
        if 'files' not in db.list_collection_names():
            db.create_collection('files')
            print("已创建files集合")
        
        # 初始化数据库
        init_database(db)
        
        # 创建索引
        create_indexes(db)
        
        return True
    except Exception as e:
        print(f"初始化数据库失败: {str(e)}")
        return False

if __name__ == "__main__":
    init_db() 